#include "head.h"
#include"get_id.h"
//#include"select_id.h"
sqlite3 *db = NULL;


int main()
{
    // 数据库初始化
    if (sql_init(&db))
    {
        printf("sqlite3_init error\n");
        return -1;
    }

    /*与客户端的连接*/
    /*1. 创建套接字*/
    int sfd = socket(AF_INET, SOCK_STREAM, 0); // tcp
    if (sfd < 0)
    {
        perror("socket");
        return -1;
    }
    // 允许地址重用
    int on = 1;
    setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    printf("socket success!\n");

    /*2. 绑定本机地址和端口*/
    struct sockaddr_in srvaddr;
    memset(&srvaddr, 0, sizeof(srvaddr));
    srvaddr.sin_family = AF_INET;                        // IPv4地址族
    srvaddr.sin_port = htons(9999);                      // 端口号
    srvaddr.sin_addr.s_addr = inet_addr("192.168.2.17"); // IPv4地址
    if (0 > bind(sfd, (struct sockaddr *)&srvaddr, sizeof(srvaddr)))
    {
        perror("bind");
        return -1;
    }
    printf("bin success!\n");

    /*3. 设置监听套接字*/
    if (0 > listen(sfd, 5))
    {
        perror("listen");
        return -1;
    }
    printf("listen success!\n");

    while (1)
    {
        struct sockaddr_in cliaddr;
        int addrlen = sizeof(cliaddr);

        int cfd = accept(sfd, (struct sockaddr *)&cliaddr, &addrlen);
        if (cfd < 0)
        {
            perror("accept");
            continue;
        }
        printf("accept: %s %d!\n", inet_ntoa(cliaddr.sin_addr),
               ntohs(cliaddr.sin_port));
        printf("cfd :%d\n", cfd);
        pthread_t thread; // 使用线程
        pthread_create(&thread, NULL, thread_choice, (void *)cfd);
        pthread_detach(thread);
    }
    close(sfd);
    sqlite3_close(db);
    return 0;
}
//线程函数
void *thread_choice(void *arg)
{

    int cfd = (int)arg;
    while (1)
    {
        char order[256] = {0};
        if (0 >= recv(cfd, (char *)&order, sizeof(order), 0))
        {
            close(cfd);
            pthread_exit(NULL);
        }

        printf("type,name&pwd:%s\n", order);

        switch (order[0])
        {
        case 'L':
        {
            if (do_login(cfd, db, order) == 0)
            {
                printf("login success\n");

                Click_where(cfd);
            }
            break;
        }
        case 'R':
            printf("is R-->%c", order[0]);
            do_register(cfd, db, order);
            break;
        default:
            break;
        }
    }
}
//登录
int do_login(int cfd, sqlite3 *db, const char *order)
{
    char ch;
    int flag=0;//判断登录成功失败的标志
    char name[64], pswd[64], buf[130], sql[256];
    snprintf(buf, sizeof(buf), "%s", order);
     printf("login  %s\n", order);
    sscanf(buf, " %c %s %s", &ch, name, pswd); // 解析账号与密码
    printf("ch:%c,name:%s,pwd: %s\n", ch, name, pswd);
    char *errmsg = NULL;
    int nrow, ncolumn;
    char **resultp = NULL;
    memset(buf, 0, sizeof(buf));
    sprintf(sql, "select * from user where name='%s' and pswd='%s'", name, pswd);
    if (0 != sqlite3_get_table(db, sql, &resultp, &nrow, &ncolumn, &errmsg))
    {
        fprintf(stderr, "查询失败: %s\n", errmsg);
        sqlite3_free(errmsg);
        return -1;
    }
    else
    {
        if (nrow > 0)
        {
            sprintf(buf, "YY");
        }
        else{
            flag =1;
            sprintf(buf, "NN");
        }
    }

    if (0 >= send(cfd, buf, strlen(buf), 0)) // 发送查找的结果给客户端
    {
        perror("send_error");
        return -1;
    }
if(flag==0)
    return 0;//登录成功，跳转到登录后页面操作的函数
    else return -1;//失败则继续进行登录注册判断
}
void do_register(int cfd, sqlite3 *db, const char *order)
{
    char ch;
    char name[64], pswd[64], buf[130], sql[256];
    snprintf(buf, sizeof(buf), "%s", order); // buf=order
    //printf("register  %s\n", order);
    sscanf(buf, " %c %s %s", &ch, name, pswd); // 解析账号与密码
    //printf("name:%s,pwd: %s\n", name, pswd);
    char *errmsg = NULL;
    int nrow, ncolumn;
    char **resultp = NULL;
    memset(buf, 0, sizeof(buf));
    sprintf(sql, "select * from user where name='%s'", name);
    if (0 != sqlite3_get_table(db, sql, &resultp, &nrow, &ncolumn, &errmsg))
    {
        fprintf(stderr, "SQL select error: %s\n", errmsg);
        sqlite3_free(errmsg); // 必须释放错误消息内存
        return;
    }
    else if (nrow > 0)
    { // 账号已存在
        sprintf(buf, "NE");
        printf("NE\n");
    }
    else
    {
        memset(sql, 0, sizeof(sql));
        sprintf(sql, "insert into  user values('%s','%s')", name, pswd);
        if (0 != sqlite3_exec(db, sql, NULL, NULL, &errmsg))
        {
            fprintf(stderr, "SQL insert error: %s\n", errmsg);
            sqlite3_free(errmsg); // 必须释放错误消息内存
            return;
        }
        else
        {
            sprintf(buf, "YY"); // yes
            printf("YY\n");
        }
    }

    printf("buf: %s\n", buf);
    if (0 >= send(cfd, buf, strlen(buf), 0)) // 发送查找的结果给客户端
    {
        perror("send_error");
        return;
    }
}
//
int sql_init(sqlite3 **db)
{
    /*数据库初始化*/
    if (0 != sqlite3_open("user.db", db))
    {
        fprintf(stderr, "sqlite3_open: %s\n", sqlite3_errmsg(*db));
        return -1;
    }
    printf("open database success!\n");
    /*执行sql语句: 创建用户信息表*/
    char *errmsg = NULL;
    char sql[128] = "create table if not exists user(name text primary key, pswd text)";
    if (0 != sqlite3_exec(*db, sql, NULL, NULL, &errmsg))
    {
        fprintf(stderr, "sqlite3_exec: %s\n", errmsg);
        return -1;
    }
    printf("create user success!\n");

    /*执行sql语句: 创建快递信息表*/
    memset(sql, 0, sizeof(sql));
    //information存放快递信息的表
    strcpy(sql, "create table if not exists information(id primary key, mesg text,storehouse text)");
    if (0 != sqlite3_exec(*db, sql, NULL, NULL, &errmsg))
    {
        fprintf(stderr, "sqlite3_exec: %s\n", errmsg);
        return -1;
    }
    printf("create information success!\n");

    return 0;
}

// 初始化查询结果
void init_query_result(QueryResult *result, int initial_capacity)
{
    result->rows = (char **)malloc(initial_capacity * sizeof(char *));
    result->row_count = 0;
    result->capacity = initial_capacity;
}
 //释放查询结果
void free_query_result(QueryResult *result)
{
    for (int i = 0; i < result->row_count; i++)
    {
        free(result->rows[i]);
    }
    free(result->rows);
    result->row_count = 0;
    result->capacity = 0;
}
// 回调函数
static int callback(void *data, int argc, char **argv, char **azColName)
{
    QueryResult *result = (QueryResult *)data;
    char row_buffer[1024] = {0};

    // 构建格式化的字符串
    for (int i = 0; i < argc; i++)
    {
        if (i > 0)
        {
            strcat(row_buffer, ",");
        }
        strcat(row_buffer, argv[i] ? argv[i] : "NULL");
    }
    // 检查是否需要扩容
    if (result->row_count >= result->capacity)
    {
        result->capacity *= 2;
        result->rows = (char **)realloc(result->rows, result->capacity * sizeof(char *));
    }

    // 分配内存并存储结果
    result->rows[result->row_count] = strdup(row_buffer);
    result->row_count++;

    return 0;
}
//
int query_and_store_dynamic(sqlite3 *db,  char ch, QueryResult *result)
{
    char sql[256];
    char *errmsg = NULL;
    printf("%c\n",ch);
    if(ch == 'D')//D表示查询所有
    {
    snprintf(sql, sizeof(sql), "select * from information ;"); 
    }
   else{//按(A/B/C)查找
   sprintf(sql, "select * from information where storehouse= '%c';", ch);
   }
    if (0 != sqlite3_exec(db, sql, callback, result, &errmsg))
    {
        fprintf(stderr, "285sqlite3_exec: %s\n", errmsg);
        sqlite3_free(errmsg);
        return -1;
    }
    return 0;
}
//发送结束标志
void send_char(int cfd,char ch)
{
 char asterisk = ch;
        ssize_t bytes_sent = send(cfd, &asterisk, 1, 0);
        if (bytes_sent == -1)
        {
            perror("发送失败");
        }
        else if (bytes_sent != 1)
        {
            printf("只发送了 %zd 字节，预期 1 字节\n", bytes_sent);
        }
        else
        {
            if(ch=='@')
            printf("成功发送字符: %c\n",ch);
        }
}
//判断是那个按键被按下（A/B/C/D/Q）
int Click_where(int cfd)
{
    while (1)
    {
        char commod = 0;
        ssize_t n = recv(cfd, &commod, sizeof(commod), 0);
        if (n <= 0)
        {
            if (n == 0)
            {
                printf("客户端[%d]断开连接\n", cfd);
                break;
            }
            else
            {
                perror("recv");
                return -1;
            }
        }
        printf("comd %c\n", commod);
        switch (commod)
        {
        case 'A':
            select_where('A', db, cfd);
            break;
        case 'B':
            select_where('B', db, cfd);
            break;
        case 'C':
            select_where('C', db, cfd);
            break;
        case 'D':
            select_where('D', db, cfd);
            break;
        case 'Q':
            select_infrom_id(db,cfd);
            break;
        default:
            break;
        }
    }
    return 0;
}
//根据按键按下查询对应的信息
int select_where(char ch, sqlite3 *db, int cfd)
{
    //printf("recv : %c\n", ch);
  
    char *errmsg = NULL;
    char sql[128] = {0};

    QueryResult result;
    init_query_result(&result, 10); // 初始容量10
    if (query_and_store_dynamic(db, ch, &result) == 0)
    {
        printf("查询结果(共%d行):\n", result.row_count);
        for (int i = 0; i < result.row_count; i++)
        {
            printf("行%d: %s\n", i + 1, result.rows[i]);
            if (0 >= send(cfd, result.rows[i], strlen(result.rows[i]), 0)) // 发送查找的结果给客户端
            {
                perror("send387_error");
                return -1;
            }
            send_char(cfd,'\n');
        }
        //发送接收标志 @
       send_char(cfd,'@');
    }
    // 使用完后释放内存
    free_query_result(&result);
    return 0;
}
//搜索时调用该函数
int select_infrom_id(sqlite3 *db, int cfd)
{
  //  printf("recv Q\n");
    char recevier[256] = {0};
    char recvq[256]={0};
    while(strlen(recevier)<3)//搜索的id大于3字节//过滤Q
    {
        memset(recevier,0,sizeof(recevier));
     if (0>= recv(cfd, (char *)&recevier, sizeof(recevier), 0))
    {
        perror("recv395： error");
        return -1; 
    }
    printf("400recev:%s\n",recevier);
    printf("euio  %ld\n",strlen(recevier));
    }
  if (recevier[0] == 'Q' && strlen(recevier) > 1) {//接收到的数据为”Q+express_no“，去除Q
    size_t copy_len = strlen(recevier) - 1;
    memcpy(recvq, recevier + 1, copy_len);
    recvq[copy_len] = '\0';  // 手动添加终止符
}
    else{
        strcpy(recvq,recevier);
    }
     printf("413ecev:%s\n",recvq);
    char sql[512]={0};
     char *errmsg = NULL;
    int nrow, ncolumn;
    char **resultp = NULL;
     char buf[512]={0};
     sprintf(sql, "select * from information where id='%s'",recvq);
    if (0 != sqlite3_get_table(db, sql, &resultp, &nrow, &ncolumn, &errmsg))
    {
        fprintf(stderr, "SQL select_inform398 error: %s\n", errmsg);
        sqlite3_free(errmsg); // 必须释放错误消息内存
        return -1;
    }
    else if (nrow ==1)
    {   //查询到信息，每列数据后面添加',',保证格式相同。"四川成都 北京什刹海,B"
    for (int i = 0; i < ncolumn; i++)
    {
        if(i!=0){
            strcat(buf,",");
        }
        strcat(buf,resultp[ncolumn + i]);   
    }
    strcat(buf,"\n");//末尾添加换行，qt以"\n"作为分割处理数据
    printf("查询到： %s",buf);
     if(0>=send(cfd,buf,sizeof(buf),0))
     {
        printf("send defalut!\n");
     } 
    }
    //发送结束标志 @
    send_char(cfd,'@');
    sqlite3_free_table(resultp);
    return 0;
}
